'''
    data-type.py
    author: yizimi-yuanxin 
    update: 3.15
'''

def list_hex_print(a: list):
    print('[', end='')
    for x in a:
        print(hex(x), end=', ')
    print(']')

class msg_segment(object):
    '''
    报文字段：
    报文字段代表的是报文中具有特定含义的一段字段
    比如：IP路段的dst addr字段
    seg_name: 字段名称
    seg_len: 字段长度（byte数）
    seg_data: 报文数据（二进制转为十进制），此处可能还是一个报文，递归分析
    '''
    seg_name = ""
    seg_len = 0
    seg_data = 0x000000
    def __init__(self, name: str, len: int, data):
        self.seg_name = name
        self.seg_len = len
        self.seg_data = data


class msg_struct(object):
    '''
    报文：
    一个完整的报文
    比如一个IP报文
    msg_len: 报文总长度(byte)
    msg_size: 报文的字段数量
    msg_mode_id: 报文类型，此处主要指网络的哪一层，比如网络层
    msg_seg: 报文具体的字段，此处为列表，列表中元素为 msg_segment 类型
    '''
    msg_len = 0
    msg_size = 0
    msg_mode_id = 0
    msg_seg = []
    def __init__(self, len: int, mode_id: int):
        '''
        初始化，只需要报文总类型和报文类型，具体的报文解析在其他函数中
        '''
        self.msg_len = len
        self.msg_size = 0
        self.msg_mode_id = mode_id
        self.msg_seg = list()
        self.msg_data_name = ""
        self.msg_datalen = 0
        
    def add_seg(self, seg: msg_segment):
        '''
        添加报文字段
        '''
        self.msg_seg.append(seg)
        self.msg_size += 1
        self.msg_len += seg.seg_len
        # print('%s add seg: %s' % (self.msg_mode_id, seg.seg_name))
        
    def Print(self, dep=0):
        '''
        输出报文分析
        '''
        print("\t" * dep, end='')
        print("msg: ", self.msg_mode_id)
        print("\t" * dep, end='')
        print("len: %d, size of seg: %d" % (self.msg_len, self.msg_size))
        # print(len(self.msg_seg))
        for seg in self.msg_seg:
            print("\t" * dep, end='')
            print("\tseg_name: %s, seg_len: %d" % (seg.seg_name, seg.seg_len))
            print("\t" * dep, end='')
            print("\tseg data: ")
            print("\t" * dep, end='')
            if type(seg.seg_data) == msg_struct:
                # print(seg.seg_data)
                seg.seg_data.Print(dep + 1)
                pass    
            else:
                if type(seg.seg_data) == list:
                    list_hex_print(seg.seg_data)
                else:
                    print(seg.seg_data)
                pass
            
            
class msg_mode(object):
    '''
    报文分析模式
    表示报文格式的结构
    mode_id: 模式的id号
    mode_name: 模式的名称
    mode_size: 模式的字段数
    '''
    mode_id = 0
    mode_name = ""
    mode_size = 0
    mode = []
    datalen = 0
    datalen_name = ""
    def __init__(self, modeid: int, modename: str):
        self.mode_id = modeid
        self.mode_size = 0
        self.mode_name = modename
        self.mode.clear()
    def add_mode_seg(self, seglen: int, segname: str):
        self.mode.append((segname, seglen))
        self.mode_size += 1
    def set_data_name(self, name: str):
        self.datalen_name = name


def Matching_message(string: list, mode: list, dep = 0):  
    '''
    根据给定报文分析模式进行分析报文
    string: 报文的二进制文件，格式为list，每个元素代表1byte，方便小端
    mode: 元素为msg_mode的list
    '''
    if (len(mode) != 0):
        print(mode[0].mode_name)
    # print('dep: ', dep)
    dep += 1
    if len(mode) == 0 or mode[0].mode_id == 0x0:
        strlen = len(string)
        # print(type(string))
        temp = msg_segment('data', strlen, string)
        msg = msg_struct(0, 0x0)
        msg.add_seg(temp)
        # print(msg)
        return (msg, [])
    now_mode = mode[0]
    now_msg = msg_struct(0, now_mode.mode_id)
    mode = mode[1:]
    pointer = 0
    # remain_seg = len(now_mode.mode)
    for segname, seglen in now_mode.mode:
        # print(now_mode.mode_id, segname, seglen)
        if segname == 'data':
            # print('data:',)
            length_from_data = now_mode.datalen
            (ret, tmp) = Matching_message(string[pointer: pointer + length_from_data], mode, dep)
            # print(ret.msg_seg[0].seg_data)
            temp = msg_segment(segname, ret.msg_len, ret)
            # print(temp.seg_data)
            pointer += ret.msg_len
            # now_msg.msg_len += ret.msg_len
        else:
            # print(segname)
            data = string[pointer: pointer + seglen]
            # print(data)
            len_data = len(data)
            ret = 0
            for i in range(len_data):
                ret = ret + data[i] * (0x100)**i
            temp = msg_segment(segname, seglen, ret)
            pointer += seglen
            # now_msg.msg_len += seglen
            if segname == now_mode.datalen_name:
                now_mode.datalen = ret
                # print('datalen', ret)
        # print("now", now_msg.msg_len)
        now_msg.add_seg(temp)
    # print(now_msg)
    return (now_msg, string[pointer: ])

